﻿using EMall.Application;
using EMall.Query;
using EMall.Uow;
using Microsoft.EntityFrameworkCore;

namespace EMall.ProductService.Categories
{
    public class CategoryAppService : ApplicationService, ICategoryAppService
    {
        private readonly ICategoryRepository _categoryRepository;
        private readonly CategoryManager _categoryManager;
        public CategoryAppService(
            ICategoryRepository categoryRepository,
            CategoryManager categoryManager)
        {
            _categoryRepository = categoryRepository;
            _categoryManager = categoryManager;
        }
        [UnitOfWork]
        public async Task CreateAsync(CreateCategoryDto input)
        {
            var name = await _categoryManager.CheckNameExistsAsync(input.Name);
            var code = await _categoryManager.GenerateCodeAsync(input.ParentId);
            var category = new Category(name, code, input.ParentId);
            await _categoryRepository.AddAsync(category);
        }
        [UnitOfWork]
        public async Task UpdateAsync(UpdateCategoryDto input)
        {
            var category = await _categoryRepository.GetAsync(input.Id);
            var newName = await _categoryManager.CheckNewNameExistsAsync(category, input.Name);
            var newCode = await _categoryManager.GenerateNewCodeAsync(category, input.ParentId);
            category.Update(newName, newCode, input.ParentId);
        }
        [UnitOfWork]
        public async Task DeleteAsync(DeleteCategoryDto input)
        {
            var product = await _categoryRepository.GetAsync(input.Id);
            await _categoryRepository.RemoveAsync(product);
        }
        public async Task<CategoryDto> GetAsync(int id)
        {
            var category = await QueryService.GetAsync<Category, int>(id);
            return Mapper.Map<CategoryDto>(category);
        }
        public async Task<IEnumerable<CategoryListDto>> GetListAsync(GetCategoryListQueryDto input)
        {
            var data = await QueryService.GetQueryable<Category>()
               .Sorting(input.Sorting)
               .ToListAsync();
            return Mapper.Map<List<Category>, List<CategoryListDto>>(data);
        }
        public async Task<IPagedList<CategoryListDto>> GetPagedListAsync(GetCategoryListPagingAndSortingQueryDto input)
        {
            var pagedData = await QueryService.GetQueryable<Category>()
                .WhereIF(input.ParentId.HasValue, o => o.ParentId == input.ParentId)
                .Sorting(input.Sorting)
                .ToPagedListAsync(input.PageIndex, input.PageSize);
            return Mapper.Map<Category, CategoryListDto>(pagedData);
        }
        public async Task<CategoryTree> GetTreeAsync()
        {
            var data = await QueryService.GetQueryable<Category>()
            .Select(o => new CategoryTree
            {
                Id = o.Id,
                Name = o.Name,
                Code = o.Code,
                ParentId = o.ParentId,
            }).ToListAsync();
            return TreeBuilder.Build<CategoryTree, int>(data, 0);
        }
    }
}